/*
 *---------------------------------------------------------------
 *                        Lvgl 字体工具
 *
 * 注: 使用 Unicode 编码
 * 注: 本字体文件由 Lvgl Font Tool V0.4 生成
 * 作者: 阿里 (qq:617622104)
 *---------------------------------------------------------------
 */
#include <assert.h>
#include "lvgl.h" // 引入 LVGL 图形库头文件
#include "esp_partition.h"
#include "esp_log.h"
#include "myFont.h"

static const char *TAG = "myFont"; // 日志标签
// 定义 XBF 字体头结构体
typedef struct
{
    uint16_t min;        // 字体支持的最小 Unicode 字符编码
    uint16_t max;        // 字体支持的最大 Unicode 字符编码
    uint8_t bpp;         // 位深度 (Bits Per Pixel)，表示每个像素占用的位数
    uint8_t reserved[3]; // 保留字段（用于字节对齐）
} x_header_t;

// 定义字形位置索引结构体（实际未直接使用）
typedef struct
{
    uint32_t pos; // 字形数据在字体文件中的位置偏移量
} x_table_t;

// 定义字形描述信息结构体
typedef struct
{
    uint8_t adv_w; // 字形绘制后的前进宽度（像素）
    uint8_t box_w; // 字形位图宽度（像素）
    uint8_t box_h; // 字形位图高度（像素）
    int8_t ofs_x;  // X 方向偏移量（相对绘制起点）
    int8_t ofs_y;  // Y 方向偏移量（相对基线）
    uint8_t r;     // 保留字段（用于填充）
} glyph_dsc_t;

// 声明全局字体头信息结构体
static x_header_t __g_xbf_hd = {
    .min = 0x0020, // 最小 Unicode 字符（空格）
    .max = 0x9fa5, // 最大 Unicode 字符（汉字扩展）
    .bpp = 4,      // 4bpp = 16 级灰度
};

// 静态字体缓冲区（示例，实际使用时需根据存储介质修改）
// static uint8_t __g_font_buf[176];  // 如果 bin 文件存储在 SPI FLASH 中可使用此缓冲区

/**
 * @brief 从存储介质获取字体数据
 * @param offset 数据在字体文件中的偏移量
 * @param size 需要读取的数据大小
 * @return 数据指针
 *
 * 注意：此函数需要根据实际存储位置实现：
 *   - SPI FLASH: 使用 SPIFLASH_Read(__g_font_buf, offset, size)
 *   - SDRAM: 直接返回地址指针 return (uint8_t*)(sdram_address + offset)
 */
// static uint8_t __g_font_buf[714]; //如bin文件存在SPI FLASH可使用此buff

// static esp_partition_t *partition_font = NULL;

// static uint8_t *__user_font_getdata(int offset, int size)
// {
//     //如字模保存在SPI FLASH, SPIFLASH_Read(__g_font_buf,offset,size);
//     //如字模已加载到SDRAM,直接返回偏移地址即可如:return (uint8_t*)(sdram_fontddr+offset);

//     if (partition_font == NULL) {
//         partition_font = esp_partition_find_first(0x50, 0x32, &quot; font_cn_32 & quot;);
//         assert(partition_font != NULL);
//     }

//     esp_err_t err = esp_partition_read(partition_font, offset, __g_font_buf, size); //读取数据
//     if (err != ESP_OK) {
//         printf(&quot; Failed to reading cn font date\n & quot;);
//     }

//     return __g_font_buf;
// }



/*font_partition, 0xaa, 0xaa, , 4M*/


const void *map_ptr=NULL;
esp_partition_mmap_handle_t map_handle;
void font_flash_mmap(void)
{
    // Find the partition map in the partition table
    const esp_partition_t *partition = esp_partition_find_first(FONT_TYPE_AND_SUBTYPE, FONT_TYPE_AND_SUBTYPE, FONT_PARTITION_NAME);
    assert(partition != NULL);

    // Map the partition to data memory
    ESP_ERROR_CHECK(esp_partition_mmap(partition, 0, partition->size, ESP_PARTITION_MMAP_DATA, &map_ptr, &map_handle));
    ESP_LOGI(TAG, "Mapped partition to data memory address %p, size %d", map_ptr, partition->size);
}
/*仅在程序生命周期结束前不再需要释放资源的场景下，可以不调用（但不推荐）：*/
/*这个字库在lvgl运行时要一直存在，所以这个函数不会被调用*/
void font_flash_munmap(void)
{
    map_ptr = NULL;
    // Unmap the partition from data memory
    // Unmap mapped memory
    esp_partition_munmap(map_handle);
    ESP_LOGI(TAG, "Unmapped partition from data memory");
}

/**
 * @brief 获取字符位图数据
 * @param font 字体指针（未使用）
 * @param unicode_letter 目标字符的 Unicode 编码
 * @return 位图数据指针（失败返回 NULL）
 */
static const uint8_t *__user_font_get_bitmap(const lv_font_t *font, uint32_t unicode_letter)
{

    // 检查 Unicode 是否在支持范围内
    if (unicode_letter > __g_xbf_hd.max || unicode_letter < __g_xbf_hd.min) {
        return NULL;
    }
    //字库有没有映射到内存
    assert(map_ptr != NULL);

    // 计算字符在索引表中的位置
    uint32_t unicode_offset = sizeof(x_header_t) + (unicode_letter - __g_xbf_hd.min) * 4;

    // 读取该字符的数据偏移量
    //uint32_t *p_pos = (uint32_t *)__user_font_getdata(unicode_offset, 4);
    uint32_t *p_pos = (uint32_t *)((uint8_t*)map_ptr+unicode_offset);

    // 检查是否存在有效数据
    if (p_pos[0] != 0)
    {
        uint32_t pos = p_pos[0]; // 获取字形数据位置

        // 读取字形描述信息
        //glyph_dsc_t *gdsc = (glyph_dsc_t *)__user_font_getdata(pos, sizeof(glyph_dsc_t));
        glyph_dsc_t *gdsc = (glyph_dsc_t *)((uint8_t *)map_ptr+pos);

        // 计算位图数据大小并返回指针
        uint32_t bmp_size = gdsc->box_w * gdsc->box_h * __g_xbf_hd.bpp / 8;
        //return __user_font_getdata(pos + sizeof(glyph_dsc_t), bmp_size);
        return ((uint8_t *)map_ptr+ (pos + sizeof(glyph_dsc_t)));
    }
    return NULL; // 未找到字符数据
}
// 换行符 (U+000A) 的字形描述
static const lv_font_glyph_dsc_t newline_glyph_dsc = {
    .resolved_font = NULL, // 不使用解析字体
    .adv_w = 0,            // 前进宽度为0（不占用水平空间）
    .box_w = 0,            // 包围盒宽度0
    .box_h = 0,            // 包围盒高度0
    .ofs_x = 0,            // X偏移0
    .ofs_y = 0,            // Y偏移0
    .bpp = 0,              // 位深度0（无位图）
    .is_placeholder = 0    // 不是占位符
};

/**
 * @brief 获取字符描述信息
 * @param font 字体指针（未使用）
 * @param dsc_out 输出字形描述结构
 * @param unicode_letter 目标字符 Unicode
 * @param unicode_letter_next 下一个字符（未使用）
 * @return true 成功, false 失败
 */
static bool __user_font_get_glyph_dsc(const lv_font_t *font,
                                      lv_font_glyph_dsc_t *dsc_out,
                                      uint32_t unicode_letter,
                                      uint32_t unicode_letter_next)
{

    // 1. 优先处理换行符 (U+000A)
    if (unicode_letter == 61560) {
        *dsc_out = newline_glyph_dsc;
        return true;
    }
    // 检查 Unicode 范围
    if (unicode_letter > __g_xbf_hd.max || unicode_letter < __g_xbf_hd.min)
    {
        *dsc_out = newline_glyph_dsc;
        return true;
        //return false;
    }
    assert(map_ptr != NULL);
    // 计算索引位置
    uint32_t unicode_offset = sizeof(x_header_t) + (unicode_letter - __g_xbf_hd.min) * 4;

    //ESP_LOGE(TAG, "map_ptr:%p, unicode_offset:%d", map_ptr, unicode_offset);
    // 读取数据偏移量
    //uint32_t *p_pos = (uint32_t *)__user_font_getdata(unicode_offset, 4);
    uint32_t *p_pos = (uint32_t *)((uint8_t *)map_ptr + unicode_offset);

    if (p_pos[0] != 0)
    {
        // 读取字形描述信息
        // glyph_dsc_t *gdsc = (glyph_dsc_t *)__user_font_getdata(p_pos[0], sizeof(glyph_dsc_t));
        glyph_dsc_t *gdsc = (glyph_dsc_t *)((uint8_t *)map_ptr + p_pos[0]);

        // 填充 LVGL 字形描述结构
        dsc_out->adv_w = gdsc->adv_w;  // 前进宽度
        dsc_out->box_h = gdsc->box_h;  // 位图高度
        dsc_out->box_w = gdsc->box_w;  // 位图宽度
        dsc_out->ofs_x = gdsc->ofs_x;  // X 偏移
        dsc_out->ofs_y = gdsc->ofs_y;  // Y 偏移
        dsc_out->bpp = __g_xbf_hd.bpp; // 位深度

        return true;
    }
    *dsc_out = newline_glyph_dsc;
    return true;
    //ESP_LOGE(TAG, "Character %d not found in font", unicode_letter);
   // return false; // 字符不存在
}

// 字体声明
// 字体名称：Alibaba PuHuiTi 3.0 45 Light
// 字模高度：22px
// 类型：XBF 外部字体（需配套 .bin 文件）
const lv_font_t myFont = {
    .get_glyph_bitmap = __user_font_get_bitmap, // 位图获取函数
    .get_glyph_dsc = __user_font_get_glyph_dsc, // 描述信息获取函数
    .line_height = FONT_LINE_HEIGHT,            // 行高（像素）
    .base_line = 0,                             // 基线位置（从顶部偏移量）
};